package com.imooc.reader.portal.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imooc.reader.portal.dto.SmsResult;
import com.imooc.reader.portal.entity.Member;
import com.imooc.reader.portal.entity.MemberReadState;
import com.imooc.reader.portal.entity.VerificationCode;
import com.imooc.reader.portal.mapper.MemberMapper;
import com.imooc.reader.portal.mapper.MemberReadStateMapper;
import com.imooc.reader.portal.mapper.VerificationCodeMapper;
import com.imooc.reader.portal.service.MemberService;
import com.imooc.reader.portal.service.impl.exception.BusinessException;
import com.imooc.reader.portal.utils.SmsUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Random;

@Service
public class MemberServiceImpl implements MemberService {
    @Resource
    private SmsUtils smsUtils;
    @Resource
    private VerificationCodeMapper verificationCodeMapper;
    @Resource
    private MemberMapper memberMapper;
    @Resource
    private MemberReadStateMapper memberReadStateMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void sendVCode(String mobile) {
        String vcode = this.generateRandomCode(4);
        try {
            SmsResult smsResult = smsUtils.sendVerifyCode(mobile, vcode);
            if(!smsResult.getCode().equals("OK")){
                throw new BusinessException(smsResult.getCode(), smsResult.getMessage());
            }
            QueryWrapper condition = new QueryWrapper();
            condition.eq("mobile", mobile);
            condition.eq("state", 0);
            List<VerificationCode> codeList = verificationCodeMapper.selectList(condition);
            for(VerificationCode vc:codeList){
                vc.setState(2);
                verificationCodeMapper.updateById(vc);
            }

            VerificationCode verificationCode = new VerificationCode();
            verificationCode.setMobile(mobile);
            verificationCode.setSendTime(new Date());
            verificationCode.setExpireTime(calculateExpireTime(5));
            verificationCode.setState(0);
            verificationCode.setVerificationCode(vcode);
            verificationCodeMapper.insert(verificationCode);

        } catch (Exception e) {
            throw new BusinessException(e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Member register(String mobile, String vcode) {
        QueryWrapper condition = new QueryWrapper();
        Date now = new Date();
        condition.ge("expire_time", now);
        condition.eq("state", 0);
        condition.eq("verification_code", vcode);
        condition.eq("mobile", mobile);
        condition.orderByDesc("send_time");
        List<VerificationCode> codeList = verificationCodeMapper.selectList(condition);
        if(codeList.size() > 0){
            QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
            memberQueryWrapper.eq("mobile", mobile);
            List<Member> members = memberMapper.selectList(memberQueryWrapper);
            Member member = null;
            if(members.size() > 0 ){
                member = members.get(0);
            }else{
                member = new Member();
                member.setMobile(mobile);
                member.setNickname("慕粉" + mobile.substring(6,10));
                member.setCreateTime(now);
                memberMapper.insert(member);
            }
            VerificationCode vc = codeList.get(0);
            vc.setState(1);
            vc.setVerifyTime(now);
            vc.setMemberId(member.getMemberId());
            verificationCodeMapper.updateById(vc);
            return member;
        }else{
            throw new BusinessException("INVALID_VERIFICATION_CODE", "无效验证码");
        }

    }

    @Override
    public Member selectById(Long memberId) {
        return memberMapper.selectById(memberId);
    }

    @Override
    public MemberReadState selectMemberReadState(Long memberId, Long bookId) {
        QueryWrapper<MemberReadState> wrapper = new QueryWrapper<>();
        wrapper.eq("book_id", bookId);
        wrapper.eq("member_id", memberId);
        MemberReadState memberReadState = memberReadStateMapper.selectOne(wrapper);
        return memberReadState;

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public MemberReadState updateMemberReadState(Long memberId, Long bookId, Integer readState) {
        QueryWrapper<MemberReadState> wrapper = new QueryWrapper<>();
        wrapper.eq("book_id", bookId);
        wrapper.eq("member_id", memberId);
        MemberReadState memberReadState = memberReadStateMapper.selectOne(wrapper);
        if(memberReadState == null){
            memberReadState = new MemberReadState();
            memberReadState.setMemberId(memberId);
            memberReadState.setBookId(bookId);
            memberReadState.setReadState(readState);
            memberReadState.setCreateTime(new Date());
            memberReadStateMapper.insert(memberReadState);
        }else{
            memberReadState.setReadState(readState);
            memberReadStateMapper.updateById(memberReadState);
        }
        return memberReadState;
    }

    private String generateRandomCode(int codeLength){
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for(int i = 0 ; i < codeLength ;i++){
            code.append(random.nextInt(10));
        }
        return code.toString();
    }

    private Date calculateExpireTime(int minutes){
        long currentTimeMillis = System.currentTimeMillis();
        long expireTimeMillis = currentTimeMillis + (minutes * 60 * 1000);
        return new Date(expireTimeMillis);
    }
}
